<

dart:ffi を使用したネイティブ Android コードへのバインド

Flutter モバイル アプリとデスクトップ アプリでは、ダーツ:ffiネイティブ C API を呼び出すためのライブラリ。FFIを意味する外部関数インターフェイス。同様の機能を表すその他の用語には次のものがあります。ネイティブインターフェース言語のバインディング。

ライブラリまたはプログラムが FFI ライブラリを使用できるようになる前に ネイティブ コードにバインドするには、次のことを確認する必要があります。 ネイティブ コードがロードされ、そのシンボルが Dart に表示されます。 このページはコンパイル、パッケージ化、 Flutter プラグインまたはアプリ内で Android ネイティブ コードをロードします。

このチュートリアルでは、C/C++ をバンドルする方法を説明します。 Flutter プラグイン内のソースを使用してバインドします。 Android と iOS の両方にある Dart FFI ライブラリ。 このチュートリアルでは、C 関数を作成します 32ビット加算を実装し、 「native_add」という名前の Dart プラグインを通じてそれを公開します。

動的リンクと静的リンク

ネイティブ ライブラリはアプリにリンクできます。 動的または静的に。静的にリンクされたライブラリ アプリの実行可能イメージに埋め込まれており、 アプリの起動時に読み込まれます。

静的にリンクされたライブラリのシンボルは、 を使用してロードされましたDynamicLibrary.executableまたDynamicLibrary.process

対照的に、動的にリンクされたライブラリは分散されます。 アプリ内の別のファイルまたはフォルダーに、 そしてオンデマンドで読み込まれます。 Android では、動的に リンクされたライブラリは、次のセットとして配布されます。.so(妖精) ファイル (アーキテクチャごとに 1 つ)。

動的にリンクされたライブラリは、 ダーツヴィアDynamicLibrary.open

API ドキュメントは Dart 開発チャネルから入手できます。Dart API リファレンス ドキュメント。

Android では、動的ライブラリのみがサポートされます (主な実行可能ファイルは JVM であるため、 これには静的にリンクしません)。

FFI プラグインを作成する

「native_add」という FFI プラグインを作成するには、 以下をせよ:

$ flutter create --platforms=android,ios,macos,windows,linux --template=plugin_ffi native_add
$ cd native_add

これにより、C/C++ ソースを含むプラグインが作成されます。native_add/src。 これらのソースは、さまざまなネイティブ ビルド ファイルによってビルドされます。 OSのビルドフォルダー。

FFI ライブラリは C シンボルに対してのみバインドできます。 したがって、C++ では、これらのシンボルはマークされますextern "C"

また、次のことを示す属性も追加する必要があります。 シンボルは Dart から参照されます。 リンカーがシンボルを破棄しないようにするため リンク時の最適化中。__attribute__((visibility("default"))) __attribute__((used))

Android では、native_add/android/build.gradleコードをリンクします。

ネイティブコードはdartから呼び出されますlib/native_add_bindings_generated.dart

バインディングは次のように生成されます。パッケージ:figen。

その他の使用例

プラットフォームライブラリ

プラットフォーム ライブラリにリンクするには、 次の手順を使用してください。

  1. 目的のライブラリを見つけます。Android NDK ネイティブ APIAndroid ドキュメントのリストを参照してください。これは安定したネイティブ API のリストです。
  2. 次を使用してライブラリをロードしますDynamicLibrary.open。 たとえば、OpenGL ES (v3) をロードするには:

    DynamicLibrary.open('libGLES_v3.so');
    

Android マニフェストの更新が必要になる場合があります で示されている場合、アプリまたはプラグインのファイル ドキュメント。

ファーストパーティライブラリ

ネイティブコードをソースに組み込むプロセス コードまたはバイナリ形式がアプリで同じであるか、 プラグイン。

オープンソースのサードパーティ

フォローしてくださいC および C++ コードをプロジェクトに追加するAndroid ドキュメントの指示に従って、 ネイティブ コードとネイティブのサポートを追加する コード ツールチェーン (CMake またはndk-build)。

クローズドソースのサードパーティライブラリ

Dart を含む Flutter プラグインを作成するには ソース コードですが、C/C++ ライブラリを配布します バイナリ形式では、次の手順を使用します。

  1. を開きますandroid/build.gradleあなたのファイル 計画。
  2. AAR アーティファクトを依存関係として追加します。やめてくださいアーティファクトを含めます flutterパッケージ。代わりに、そうあるべきです リポジトリからダウンロードされたものなど Jセンター。

Android APK サイズ (共有オブジェクト圧縮)

Android のガイドライン一般的にお勧めします ネイティブ共有オブジェクトを非圧縮で配布する それは実際にデバイスのスペースを節約できるからです。 共有オブジェクトはAPKから直接ロードできます デバイス上でそれらを解凍する代わりに、 一時的な場所に置いてからロードします。 APK は輸送中にさらに梱包されます。 ダウンロード サイズを確認する必要がある理由。

Flutter APK はデフォルトでこれらのガイドラインに従っていません そして圧縮するlibflutter.solibapp.so-これ APK サイズは小さくなりますが、デバイス サイズは大きくなります。

サードパーティからの共有オブジェクトにより、このデフォルトが変更される可能性があります で設定android:extractNativeLibs="true"彼らの中でAndroidManifest.xmlの圧縮を停止しますlibflutter.solibapp.so、およびユーザーが追加した共有オブジェクト。 圧縮を再度有効にするには、次の設定をオーバーライドします。your_app_name/android/app/src/main/AndroidManifest.xml次の方法で。

@@ -1,5 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.example.your_app_name">
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.example.your_app_name" >
     <!-- io.flutter.app.FlutterApplication is an android.app.Application that
          calls FlutterMain.startInitialization(this); in its onCreate method.
          In most cases you can leave this as-is, but you if you want to provide
          additional functionality it is fine to subclass or reimplement
          FlutterApplication and put your custom class here. -->
@@ -8,7 +9,9 @@
     <application
         android:name="io.flutter.app.FlutterApplication"
         android:label="your_app_name"
-        android:icon="@mipmap/ic_launcher">
+        android:icon="@mipmap/ic_launcher"
+        android:extractNativeLibs="true"
+        tools:replace="android:extractNativeLibs">